import urllib
import urllib2
import cherrypy as cp
from turbogears.validators import Schema, Invalid, FormValidator, \
    String
from tgcaptcha import controller
import gettext
from turbogears import config
from datetime import datetime

_ = gettext.gettext

captcha_controller = controller.CaptchaController()
        
class ValidCaptchaInput(FormValidator):
    
    messages = {'incorrect': _("Incorrect value."),
                'timeout': _("Too much time elapsed. Please try again."),
                'payload': _("Captcha Payload error")}
    
    __unpackargs__ = ('captchahidden', 'captchainput')
    
    case_sensitive = config.get('tgcaptcha.case_sensitive', True)

    timeout = int(config.get('tgcaptcha.timeout', 5))
    
    def validate_python(self, field_dict, state):
        hidden = str(field_dict['captchahidden'])
        input_val = str(field_dict['captchainput'])

        if len(hidden) != 44:
            raise Invalid(self.message('payload', state), field_dict,
                          state)
        try:
            payload = captcha_controller.model_from_payload(hidden)
        except:
            raise Invalid(self.message('incorrect', state), field_dict, state)
        if self.case_sensitive:
            if payload.plaintext != input_val:
                raise Invalid(self.message('incorrect', state), field_dict,
                state)
        else:
            if payload.plaintext.upper() != input_val.upper():
                raise Invalid(self.message('incorrect', state), field_dict,
                state)

        elapsed = datetime.utcnow() - payload.created
        if elapsed.seconds > self.timeout * 60:
            raise Invalid(self.message('timeout', state), field_dict, state)
        
        
class CaptchaFieldValidator(Schema):
    chained_validators = [ValidCaptchaInput('captchahidden', 'captchainput')]

class reCaptchaValidator(FormValidator):
    """
    @see formencode.validators.FieldsMatch
    """

    messages = {
        'incorrect': _("Incorrect value."),
    }

    verify_server           = "api-verify.recaptcha.net"
    private_key             = '6Lf-DAAAAAAAAK_YDZEgip141HW5EP7xxRZh4rCz'
    remote_ip               = ''
    field_names             = ['recaptcha_challenge_field',
                               'recaptcha_response_field']
    validate_partial_form   = True
    __unpackargs__ = ('*', 'field_names')

    def validate_partial(self, field_dict, state):
        for name in self.field_names:
            if not field_dict.has_key(name):
                return
        self.validate_python(field_dict, state)

    def validate_python(self, field_dict, state):
        challenge = field_dict['recaptcha_challenge_field']
        response = field_dict['recaptcha_response_field']

        if not (response and challenge and len(response) and len(challenge)):
            raise Invalid(self.message('incorrect', state), field_dict, state)
        params = urllib.urlencode ({
            'privatekey': self.private_key,
            'remoteip' : cp.request.remoteAddr,
            'challenge': challenge,
            'response' : response,
            })
        request = urllib2.Request (
            url = "http://%s/verify" % self.verify_server,
            data = params,
            headers = {
                "Content-type": "application/x-www-form-urlencoded",
                "User-agent": "reCAPTCHA Python"
                }
            )
        httpresp = urllib2.urlopen(request)
        return_values = httpresp.read().splitlines();
        httpresp.close();
        return_code = return_values[0]
        if not return_code == "true":
            raise Invalid(self.message('incorrect', state), field_dict, state)